/**
 * BladeX Commercial License Agreement
 * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
 * <p>
 * Use of this software is governed by the Commercial License Agreement
 * obtained after purchasing a license from BladeX.
 * <p>
 * 1. This software is for development use only under a valid license
 * from BladeX.
 * <p>
 * 2. Redistribution of this software's source code to any third party
 * without a commercial license is strictly prohibited.
 * <p>
 * 3. Licensees may copyright their own code but cannot use segments
 * from this software for such purposes. Copyright of this software
 * remains with BladeX.
 * <p>
 * Using this software signifies agreement to this License, and the software
 * must not be used for illegal purposes.
 * <p>
 * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
 * not liable for any claims arising from secondary or illegal development.
 * <p>
 * Author: Chill Zhuang (bladejava@qq.com)
 */
package org.springblade.thingsphere.manage.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.thingsphere.manage.excel.ProductExcel;
import org.springblade.thingsphere.manage.mapper.ProductMapper;
import org.springblade.thingsphere.manage.pojo.dto.MetaDataDTO;
import org.springblade.thingsphere.manage.pojo.entity.ProductEntity;
import org.springblade.thingsphere.manage.pojo.req.AddObjectModelRequestBody;
import org.springblade.thingsphere.manage.pojo.vo.ProductDetailInfo;
import org.springblade.thingsphere.manage.pojo.vo.ProductDetailVO;
import org.springblade.thingsphere.manage.pojo.vo.ProductVO;
import org.springblade.thingsphere.manage.service.IProductService;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 产品 服务实现类
 *
 * @author lhb
 * @since 2024-10-08
 */
@Service
public class ProductServiceImpl extends BaseServiceImpl<ProductMapper, ProductEntity> implements IProductService {

	@Override
	public IPage<ProductVO> selectProductPage(IPage<ProductVO> page, ProductVO product) {
		return page.setRecords(baseMapper.selectProductPage(page, product));
	}


	@Override
	public List<ProductExcel> exportProduct(Wrapper<ProductEntity> queryWrapper) {
		return baseMapper.exportProduct(queryWrapper);
	}

	@Override
	public ProductDetailVO productDetail(Long id) {
		return baseMapper.productDetail(id);
	}

	@Override
	public ProductDetailInfo productDetailInfo(Long id) {
		return baseMapper.productDetailInfo(id);
	}

	@Override
	public Boolean updateStatus(Long id, Integer status) {
		ProductEntity product = this.getById(id);
		if (null == product) {
			throw new ServiceException("产品不存在");
		}
		if (Objects.equals(product.getStatus(), status)) {
			throw new ServiceException("当前状态无需更改");
		}
		product.setStatus(status);
		return this.updateById(product);
	}

	@Override
	public boolean addObjectModel(AddObjectModelRequestBody body) {
		// 查询产品信息
		ProductEntity product = this.getById(body.getProductId());
		if (null == product) {
			throw new ServiceException("产品不存在");
		}
		// 更新属性物模型设置
		MetaDataDTO metaDataDTO = JSONObject.parseObject(product.getMetadata(), MetaDataDTO.class);
		if (null == metaDataDTO) {
			metaDataDTO = new MetaDataDTO();
		}
		List<MetaDataDTO.PropertiesDTO> properties = metaDataDTO.getProperties();
		if (CollectionUtils.isEmpty(properties)) {
			properties = new ArrayList<>();
		}

		List<MetaDataDTO.PropertiesDTO> properties2 = new ArrayList<>();
		boolean flag = true;
		Iterator<MetaDataDTO.PropertiesDTO> iterator = properties.iterator();
		while (iterator.hasNext()) {
			MetaDataDTO.PropertiesDTO next = iterator.next();
			if (next.getId().equals(body.getProperties().getId())) {
				next = body.getProperties();
				flag = false;
			}
			properties2.add(next);
		}
		if (flag) {
			properties2.add(body.getProperties());
		}
		metaDataDTO.setProperties(properties2);

		// 判断要保存的类型
		String metaDataJson = JSONObject.toJSONString(metaDataDTO);
		product.setMetadata(metaDataJson);
		if (2 == body.getSaveType()) {
			product.setMetadataUse(metaDataJson);
		}
		return this.updateById(product);
	}

	@Override
	public List<MetaDataDTO.PropertiesDTO> propertiesAttributes(Long productId) {
		ProductEntity product = this.getById(productId);
		if (null == product) {
			throw new ServiceException("产品不存在");
		}
		if (StringUtils.isBlank(product.getMetadata())) {
			return new ArrayList<>();
		}
		MetaDataDTO metaData = JSONObject.parseObject(product.getMetadata(), MetaDataDTO.class);
		return metaData.getProperties();
	}

	@Override
	public MetaDataDTO.PropertiesDTO propertiesAttributesDetail(Long productId, String propertiesId) {
		ProductEntity product = this.getById(productId);
		if (null == product) {
			throw new ServiceException("产品不存在");
		}
		MetaDataDTO metaData = JSONObject.parseObject(product.getMetadata(), MetaDataDTO.class);
		List<MetaDataDTO.PropertiesDTO> properties = metaData.getProperties();
		Optional<MetaDataDTO.PropertiesDTO> first = properties.stream().filter(v -> v.getId().equals(propertiesId)).findFirst();
		return first.orElse(null);
	}

	@Override
	public boolean delObjectModel(Long productId, String propertiesId) {
		ProductEntity product = this.getById(productId);
		if (null == product) {
			throw new ServiceException("产品不存在");
		}
		MetaDataDTO metaData = JSONObject.parseObject(product.getMetadata(), MetaDataDTO.class);
		List<MetaDataDTO.PropertiesDTO> properties = metaData.getProperties();
		List<MetaDataDTO.PropertiesDTO> finalList = new ArrayList<>();
		Iterator<MetaDataDTO.PropertiesDTO> iterator = properties.iterator();
		while (iterator.hasNext()) {
			MetaDataDTO.PropertiesDTO next = iterator.next();
			if (next.getId().equals(propertiesId)) {
				iterator.remove();
				continue;
			}
			finalList.add(next);
		}
		product.setMetadata(JSONObject.toJSONString(metaData));
		return this.updateById(product);
	}
}
